#ifndef VL_TEXT_HPP
#define VL_TEXT_HPP

#include <sstream>
#include <list>
#include <set>
#include <string>
#include <istream>
#include <iostream>
#include <cctype>

namespace vl
{

template<class To>
struct convert
{
	template<class From>
	static To value(From const& v)
	{
		std::stringstream strStream;
		strStream << v;
		To v2;
		strStream >> v2;
		return v2;
	}
};

template<>
struct convert<std::string>
{
	template<class From>
	static std::string value(From const& v)
	{
		std::stringstream strStream;
		strStream << v;
		return strStream.str();
	}
	
	static std::string value(std::string const& v)
	{
		return v;
	}
};

bool istr_cmp( std::string const& a, std::string const & b );

bool iis_prefix_of_other(
	std::string::const_iterator a,
	std::string::const_iterator ae,
	std::string::const_iterator b,
	std::string::const_iterator be
);

template<class IterA, class IterB>
inline bool istr_cmp(
	IterA a,
	IterA ae,
	IterB b,
	IterB be
)
{
	for (; a != ae && b != be;
		    ++a, ++b)
	{
		char ca = std::toupper(*a);
		char cb = std::toupper(*b);
		if(ca != cb)
			return false;
	}
	return (a == ae && b == be);
}

template<class IterB>
inline bool istr_cmp(
	char const* a,
	IterB b,
	IterB be
)
{
	for (; *a && b != be;
		    ++a, ++b)
	{
		char ca = std::toupper(*a);
		char cb = std::toupper(*b);
		if(ca != cb)
			return false;
	}
	return (!*a && b == be);
}

struct IStrCompare
{
	template<class StringT>
	bool operator()(StringT const& a, StringT const& b) const
	{
	    typename StringT::const_iterator itA, itB;
	    
	    for (itA = a.begin(), itB = b.begin();
	         itA != a.end() && itB != b.end();
	         ++itA, ++itB)
	    {
	    	char ca = std::toupper(*itA);
	    	char cb = std::toupper(*itB);
	        if(ca != cb)
	            return ca < cb;
	    }
	    
	    return a.size() < b.size();
	}
};

bool portable_getline(std::istream& str, std::string& s);

typedef std::set<std::string, IStrCompare> SortedListT;

// Common parts factored out
bool shell_complete_common(
	std::string& res,
	std::string::const_iterator b,
	std::string::const_iterator e,
	SortedListT::const_iterator& firstMatch,
	SortedListT::const_iterator& lastMatch,
	SortedListT const& sortedList);

template<class ContainerT, class GetText, class ShowAlternatives>
std::string shell_complete(
	ContainerT const& items,
	std::string::const_iterator b,
	std::string::const_iterator e,
	GetText getText,
	ShowAlternatives showAlternatives
	)
{
	size_t len = e - b;
	
	std::string s(b, e);
	
	if ( len == 0 )
		return s;

	typename ContainerT::const_iterator i = items.begin();

	SortedListT sortedList;

	for(; i != items.end(); ++i)
		sortedList.insert(getText(i));
	
	typename SortedListT::const_iterator firstMatch;
	typename SortedListT::const_iterator lastMatch;
	
	if(shell_complete_common(s, b, e, firstMatch, lastMatch, sortedList))
		showAlternatives(firstMatch, lastMatch);

	return s;
}

std::size_t levenshtein_distance(std::string const& a, std::string const& b);
std::size_t lcsubstr_sum(std::string const& a, std::string const& b);
std::size_t lcsubseq(std::string const& a, std::string const& b);
void trim(std::string& str);
void replace_all(std::string& str, std::string const& source, std::string const& dest);

}

#endif  // VL_TEXT_HPP
